/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.playground.client.websockets.application;

import com.playground.client.websockets.entity.message.Action;
import com.playground.client.websockets.entity.message.response.FullRoomResponseMessage;
import com.playground.client.websockets.entity.message.response.ReadyRoomResponseMessage;
import com.playground.client.websockets.entity.message.response.ResponseMessage;
import com.playground.client.websockets.socket.PlayerSocket;
import com.playground.client.websockets.util.JsonUtil;
import com.playground.core.entity.LoggedPlayer;
import com.playground.core.entity.Room;
import com.playground.core.entity.RoomStatus;
import com.playground.core.service.QueueService;
import com.playground.core.service.RoomService;
import java.util.Iterator;
import java.util.Observable;
import java.util.Observer;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * All subjects observed by this must send a Room object when notifying its
 * observers.
 * 
 * @author Tiago Peres
 */
public final class QueueObserver implements Observer {
    private static final QueueObserver INSTANCE = new QueueObserver();
    private QueueService queueService;
    
    private QueueObserver(){}
    
    public static QueueObserver getInstance() {
        return INSTANCE;
    }
    
    @Override
    public void update(Observable o, Object arg) {
        System.out.println("UPDATING...");
        Room room = (Room) arg;
        // send a message for each user in the room depending on the room status
        Iterator<LoggedPlayer> players = room.getPlayers().iterator();
        while(players.hasNext()){
            LoggedPlayer p = players.next();
            //System.out.println(p.getId() + " found");
            PlayerSocket socket = GameSelectionApplication.getPlayerSocketByPlayerId(p.getId());
            if (null != socket){
                sendMessage(socket, room);
            } else{
                StringBuilder sb = new StringBuilder();
                sb.append("Player with id ");
                sb.append(p.getId());
                sb.append(" is not related to a websocket.");
                Logger.getLogger(QueueObserver.class.getName()).log(Level.SEVERE,  sb.toString());
            }
        }
        
        // final changes
        switch (room.getStatus()){
            case full:
                queueService.waitForPlayersConfirmation(room);
                break;
            case ready:
                queueService.startGame(room);
                break;
            case refused:
                queueService.requeueRoom(room);
        }    
    }
    
    private void sendMessage(PlayerSocket socket, Room room){
        switch(room.getStatus()){
            // if the room got full, asks all players if they want to join the game
            case full:
                FullRoomResponseMessage fullMsg = new FullRoomResponseMessage();
                fullMsg.setRoomId(room.getId());
                fullMsg.setSuccess(true);
                socket.send(JsonUtil.getGson().toJson(fullMsg, FullRoomResponseMessage.class));
                break;
            // if every player confirmed the game, start it
            case ready:
                ReadyRoomResponseMessage readyMsg = new ReadyRoomResponseMessage();
                readyMsg.setSuccess(true);
                readyMsg.setApplication(room.getGameTitle().getName());
                socket.send(JsonUtil.getGson().toJson(readyMsg, ReadyRoomResponseMessage.class));
                break;
            //TODO: refused rooms. send a message to each user saying someone has quit the queue and that they'll return to the queue.
        }
    }

    public void setQueueService(QueueService queueService) {
        this.queueService = queueService;
    }
}
